﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Windows.Forms;

using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Drawing;

namespace mLib
{
    static class Function
    {


        static public List<byte> Uint32_2_bytes(UInt32 value)
        { 
             List<byte> bts = new List<byte>( BitConverter.GetBytes(value));
             return bts;
        }

        /// <summary>
        /// 获取新窗体相对于目标窗体居中的位置
        /// </summary>
        /// <param name="form">新窗体</param>
        /// <param name="obj">目标窗体</param>
        /// <returns>返回新窗体左上角的位置</returns>
        static public Point getWindowsCenter(Form form, Form obj)
        {
            Point center = new Point(obj.Location.X + obj.Width / 2, obj.Location.Y + obj.Height / 2);
            Point mycenter = new Point(center.X - form.Width / 2, center.Y - form.Height / 2);
            return mycenter;
        }

        static public List<int> Bytes2Int16s_LSB(byte [] bts)
        {
            List<int> intl = new List<int>();
            if (bts!=null) for (int i = 0; i < bts.Length; i += 2)
            {
                int value=0;
                if (i + 1 < bts.Length)
                {
                    value = bts[i];
                    value += (bts[i+1]*0x100);
                }
                else
                {
                    value = bts[i];
                }
                intl.Add(value);
            }
            return intl;
        }
        static public List<String> ints2strings(int[] ints)
        {
            if (ints == null) return null;
            List<String> stringl = new List<string>();
            for (int i = 0; i < ints.Length;i++ )
            {
                stringl.Add(ints[i].ToString());
            }
            return stringl;
        }
        static public String ints2string(int[] ints, String separator)
        {
            if (ints == null) return null;
            String str = "";
            for (int i = 0; i < ints.Length;i++ )
            {
                if (i != 0)
                {
                    str += separator;
                }
                str+=ints[i].ToString();
            }
            return str;
        }
        /// <summary>
        /// 将字节数组转换为十进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="length"></param>
        /// <param name="decollator">分隔符</param>
        /// <returns></returns>
        static public String bytesToDecString(byte[] bytes,int length, String decollator)
        {
            String hexString = String.Empty;
            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();
                for (int i = 0; i < length; i++)
                {
                    strB.Append(bytes[i].ToString());
                    if (decollator != null && i + 1 < length) strB.Append(decollator);
                }

                hexString = strB.ToString();
            } 
            return hexString;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        /// <param name="decollator"></param>
        /// <returns></returns>
        static public String bytesToDecString(byte[] bytes,int offset, int length, String decollator)
        {
            String hexString = String.Empty;
            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();
                for (int i = 0; i < length; i++)
                {
                    strB.Append(bytes[i + offset].ToString());
                    if (decollator != null && i + 1 < length) strB.Append(decollator);
                }

                hexString = strB.ToString();
            }
            return hexString;
        }



        /// <summary>
        /// 将byte数组转十六进制字符串
        /// </summary>
        /// <param name="bytes">byte[]</param>
        /// <param name="length">byte长度</param>
        /// <param name="decollator">分隔符</param>
        /// <returns></returns>
        static public String bytesToHexString(byte[] bytes,int length, String decollator)
        {
            String hexString = String.Empty;
            if (bytes != null)
            {
                StringBuilder strB = new StringBuilder();
                for (int i = 0; i < length; i++)
                {
                    strB.Append(bytes[i].ToString("X2"));
                    if (decollator != null && i + 1 < length) strB.Append(decollator);
                }

                hexString = strB.ToString();
            } 
            return hexString;
        }


        static public String bytesToEncodingString(byte[] bytes, int offset, int length, String encodeing = "ASCII")
        {
            System.Text.Encoding encodeing_;
            encodeing_=System.Text.Encoding.GetEncoding(encodeing);
            return encodeing_.GetString(bytes,offset,length);
        }


        /// <summary>
        /// 十六进制字符串转byte
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static List<Byte> hexStringToBytes(string str)
        {
            List<Byte> toint = new List<Byte>();
            Byte[] bytex = System.Text.Encoding.ASCII.GetBytes(str);
            //
            for (int i = 0, j = 0, z = 0, n = 0; i < bytex.Length; i++)
            {
                if ((bytex[i] >= '0' && bytex[i] <= '9') || (bytex[i] >= 'A' && bytex[i] <= 'F') || (bytex[i] >= 'a' && bytex[i] <= 'f'))
                {
                    if (j >= toint.Count)
                    {
                        toint.Add(0);
                    }
                    z = 1;
                    toint[j] *= 16;
                    toint[j] += (Byte)ASCtoByte((char)bytex[i]);
                    //
                    n++;
                    if (n >= 2)
                    {
                        z = 0; j++; n = 0;
                    }
                }
                else
                {
                    if (z == 1)
                    {
                        z = 0; j++; n = 0;
                    }
                }
            }
            return toint;
        }

        /// <summary>
        /// 十六进制字符串转byte
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int hexStringToInt(string str)
        {
            int revalue = 0;
            Byte[] bytex = System.Text.Encoding.ASCII.GetBytes(str);
            //
            for (int ii = bytex.Length, n = 0; ii >0; ii--)
            {
                int i = ii - 1;
                if ((bytex[i] >= '0' && bytex[i] <= '9') || (bytex[i] >= 'A' && bytex[i] <= 'F') || (bytex[i] >= 'a' && bytex[i] <= 'f'))
                {
                    double db= Math.Pow(16,n);
                    int sit = ASCtoByte((char)bytex[i]);
                    revalue += (int)(sit * db);
                    n++;
                }
                else
                {
                    break;
                }
            }
            return revalue;
        }
        /// <summary>
        /// 输入一个asc字符，返回对应的十六进制值
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public static int ASCtoByte(char ch)
        {
            int by = -1;
            switch (ch)
            {
                case '0': by = 0; break;
                case '1': by = 1; break;
                case '2': by = 2; break;
                case '3': by = 3; break;
                case '4': by = 4; break;
                case '5': by = 5; break;
                case '6': by = 6; break;
                case '7': by = 7; break;
                case '8': by = 8; break;
                case '9': by = 9; break;
                case 'a': by = 10; break;
                case 'b': by = 11; break;
                case 'c': by = 12; break;
                case 'd': by = 13; break;
                case 'e': by = 14; break;
                case 'f': by = 15; break;
                case 'A': by = 10; break;
                case 'B': by = 11; break;
                case 'C': by = 12; break;
                case 'D': by = 13; break;
                case 'E': by = 14; break;
                case 'F': by = 15; break;
                default: by = -1; break;
            }
            return by;
        }

        public static byte[] StructToBytes(object structObj, int size)
        {
            byte[] bytes = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷贝到byte 数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

        public static object ByteToStruct(byte[] bytes, Type type)
        {
            int size = Marshal.SizeOf(type);
            if (size > bytes.Length)
            {
                return null;
            }
            //分配结构体内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷贝到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return obj;
        }

        /// <summary>
        /// 从一个字符串中找出其中的数字
        /// </summary>
        /// <param name="str">目标字符串</param>
        /// <param name="value">转换结果返回</param>
        /// <returns>转换成功或失败</returns>
        public static Boolean StringFindNumber(String str, ref int value)
        {
            try
            {
                String outstr = Regex.Replace(str, "\\D*", "");
                value = int.Parse(outstr);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 比较两个byte数组是否相等,如果长度不相等，则长度大的数组大
        /// </summary>
        /// <param name="bts1">数组1</param>
        /// <param name="bts2">数组2</param>
        /// <returns>return=1(bts1>bts2),return=0(bts1=bts2),return=-1(bts2>bts1)</returns>
        public static int bytesCompare(byte[] bts1,byte[] bts2)
        {
            if (bts1.Length > bts2.Length)
            {
                return 1;
            }
            else if(bts1.Length < bts2.Length)
            {
                return -1;
            }
            else 
            {
                for (int i = 0; i < bts1.Length; i++)
                {
                    if (bts1[i] > bts2[i]) return 1;
                    else if (bts1[i] < bts2[i]) return -1;
                }
            }
            return 0;
        }
        /// <summary>
        /// 比较两个byte数组是否相等,如果长度不相等，则长度大的数组大
        /// </summary>
        /// <param name="bts1">数组1</param>
        /// <param name="bts2">数组2</param>
        /// <returns>return=1(bts1>bts2),return=0(bts1=bts2),return=-1(bts2>bts1)</returns>
        public static int bytesCompare(List<byte> bts1, List<byte> bts2)
        {
            if (bts1.Count > bts2.Count)
            {
                return 1;
            }
            else if (bts1.Count < bts2.Count)
            {
                return -1;
            }
            else 
            {
                for (int i = 0; i < bts1.Count; i++)
                {
                    if (bts1[i] > bts2[i]) return 1;
                    else if (bts1[i] < bts2[i]) return -1;
                }
            }
            return 0;
        }

        public static Boolean File2Bytes(String path,String filter,ref List<byte> btl,ref String filename)
        {
            try
            {
                OpenFileDialog openfile = new OpenFileDialog();
                if (path != null)
                {
                    openfile.InitialDirectory = path;
                }
                if (filter!=null)
                {
                    //savefile.Filter = "文本文件(*.txt)|*.txt";
                    openfile.Filter = filter;
                }
                openfile.RestoreDirectory = true;
                openfile.FilterIndex = 1;
                openfile.FileName = "open";
                if (openfile.ShowDialog() == DialogResult.OK)
                {
                    byte[] bts;
                    filename = openfile.SafeFileName;
                    FileStream fs = new FileStream(openfile.FileName, FileMode.Open);
                    bts = new byte[fs.Length];
                    fs.Read(bts, 0, bts.Length);
                    btl.AddRange(bts);
                    fs.Close();
                    return true;
                }
                return false;
                
            }
            catch
            {
                return false;
            }
        }


        public static Boolean Bytes2File(String path,String filter,String filename, byte[] data)
        {
            try
            {
                SaveFileDialog savefile = new SaveFileDialog();
                if (path != null)
                { 
                    savefile.InitialDirectory = path;
                }
                if (filter != null)
                { 
                    //savefile.Filter = "文本文件(*.txt)|*.txt";
                    savefile.Filter = filter;
                }
                savefile.RestoreDirectory = true;
                savefile.FilterIndex = 1;
                if (filename != null)
                {
                    savefile.FileName = filename;
                }
                else 
                {
                    savefile.FileName = "Save";
                }
                if (savefile.ShowDialog() == DialogResult.OK)
                {
                    FileStream fs = new FileStream(savefile.FileName, FileMode.Create);
                    //将byte数组写入文件中
                    fs.Write(data, 0, data.Length);
                    //所有流类型都要关闭流，否则会出现内存泄露问题
                    fs.Close();
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }

        }



        /// <summary>
        /// 保存数据到文件
        /// </summary>
        /// <param name="path">打开路径</param>
        /// <param name="data">数据</param>
        /// <param name="filter">文件类型过滤：如文本文件(*.txt)|*.txt</param>
        /// <param name="filename">保存默认文件名</param>
        /// <returns></returns>
        public static Boolean SaveData2File(String path, byte[] data,String filter,String filename)
        {
            try
            {
                SaveFileDialog savefile = new SaveFileDialog();
                savefile.InitialDirectory = path;
                savefile.Filter = filter;
                savefile.RestoreDirectory = true;
                savefile.FilterIndex = 1;
                savefile.FileName = filename;
                if (savefile.ShowDialog() == DialogResult.OK)
                {
                    FileStream save = new FileStream(savefile.FileName, FileMode.Create);
                    save.Close();
                    //
                    StreamWriter filewrite = new StreamWriter(savefile.FileName);
                    filewrite.Write(data);
                    filewrite.Close();
                }
                return true;
            }
            catch
            {
                return false;
            }

        }


        public static Boolean GetSaveFileName(String defpath, ref String path, String filter)
        {
            try
            {
                SaveFileDialog savefile = new SaveFileDialog();
                if (defpath != null)
                {
                    savefile.InitialDirectory = path;
                }
                if (filter != null)
                {
                    //savefile.Filter = "文本文件(*.txt)|*.txt";
                    savefile.Filter = filter;
                }
                savefile.RestoreDirectory = true;
                savefile.FilterIndex = 1;
                savefile.FileName = "Save";
                if (savefile.ShowDialog() == DialogResult.OK)
                {
                    path = savefile.FileName;
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }

        }




        /// <summary>
        /// 序列化类到文件
        /// </summary>
        /// <param name="path">文件起始路径</param>
        /// <param name="obj">类对象</param>
        /// <param name="filter">文件类型过滤：如文本文件(*.txt)|*.txt</param>
        /// <param name="filename">文件默认名称</param>
        /// <returns></returns>
        public static Boolean Serialize_Obj2File(String path, object obj, String filter, String filename)
        {
            try
            {
                SaveFileDialog savefile = new SaveFileDialog();
                savefile.InitialDirectory = path;
                savefile.Filter = filter;
                savefile.RestoreDirectory = true;
                savefile.FilterIndex = 1;
                savefile.FileName = filename;
                if (savefile.ShowDialog() == DialogResult.OK)
                {
                    FileStream save = new FileStream(savefile.FileName, FileMode.Create);
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(save, obj);
                    save.Close();   
                }
                return true;
            }
            catch
            {
                MessageBox.Show("配置数据写入文件失败");
                return false;
            }
        }

        /// <summary>
        /// 反序列化文件到类
        /// </summary>
        /// <param name="path">默认路径</param>
        /// <param name="filter">文件类型过滤：如文本文件(*.txt)|*.txt</param>
        /// <returns></returns>
        public static object Serialize_File2Obj(String path, String filter)
        {
            object obj=null;
            try
            {
                OpenFileDialog openfile = new OpenFileDialog();
                openfile.InitialDirectory = path;
                openfile.Filter = filter;
                openfile.RestoreDirectory = true;
                openfile.FilterIndex = 1;
                if (openfile.ShowDialog() == DialogResult.OK)
                {
                    FileStream readfile = null;
                    if (File.Exists(openfile.FileName) == true)
                    {
                        readfile = new FileStream(openfile.FileName, FileMode.Open);        //打开文件
                        readfile.Seek(0, SeekOrigin.Begin);                                 //设置文件到起始位置
                        BinaryFormatter bf = new BinaryFormatter();
                        obj = bf.Deserialize(readfile) as object;
                        readfile.Close();
                    }
                }
                else
                {
                    return null;
                }
            }
            catch
            {
                MessageBox.Show("配置数据写入文件失败");
                return null;
            }
            return obj;
        }





    }



}
